package com.whj.account.persist;

import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class AccountPersistServiceImpl implements AccountPersistService {
    public void setFile(String file) {
        this.file = file;
    }

    private String file;
    private static final String ELEMENT_ROOT = "account-persist";
    private static final String ELEMENT_ACCOUNTS = "accounts";
    private static final String ELEMENT_ACCOUNT = "account";
    private static final String ELEMENT_ACCOUNT_ID = "id";
    private static final String ELEMENT_ACCOUNT_NAME = "name";
    private static final String ELEMENT_ACCOUNT_PASSWORD = "password";
    private static final String ELEMENT_ACCOUNT_EMAIL = "email";
    private static final String ELEMENT_ACCOUNT_ACTIVATED = "activated";

    private Document readDocument()
            throws AccountPersistException
    {
        File dataFile = new File(this.file);
        if(!dataFile.exists()){
            //创建默认配置文件
            dataFile.getParentFile().mkdirs();

            Document document = DocumentHelper.createDocument();
            Element root = document.addElement(ELEMENT_ROOT);

            Element author1 = root.addElement(ELEMENT_ACCOUNTS);

            writeDocument(document);
        }

        //读取文件
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(dataFile);
            return document;
        }catch (DocumentException exp){
            throw new AccountPersistException("读取配置文件失败" + dataFile.getAbsolutePath(), exp);
        }
    }
    private void writeDocument(Document document)
    throws AccountPersistException{
        // lets write to a file
        try {
            try (FileWriter fileWriter = new FileWriter(file)) {
                XMLWriter writer = new XMLWriter(fileWriter,OutputFormat.createPrettyPrint());
                writer.write(document);
                writer.flush();
                writer.close();
            }
        }catch (IOException exp){
            throw new AccountPersistException("写入XML文件失败" + file, exp);
        }
    }

    private void removeElements(String userId, Document document){
        List<Element> elements = findAccountElement(userId, document);
        elements.forEach((element)->{ element.getParent().remove(element); });
    }

    private Account buildAccount(Element element){
        Account account = new Account();
        account.setId(element.elementText(ELEMENT_ACCOUNT_ID));
        account.setName(element.elementText(ELEMENT_ACCOUNT_NAME));
        account.setPassword(element.elementText(ELEMENT_ACCOUNT_PASSWORD));
        account.setEmail(element.elementText(ELEMENT_ACCOUNT_EMAIL));
        account.setActivated(Boolean.parseBoolean(element.elementText(ELEMENT_ACCOUNT_ACTIVATED)));

        return account;
    }
    private List<Element> findAccountElement(String id, Document document)
    {
        String xpath = String.format("/%s/%s/%s[./id='%s']",ELEMENT_ROOT, ELEMENT_ACCOUNTS, ELEMENT_ACCOUNT, id);
        return (List<Element>)(List)document.selectNodes(xpath);
    }

    @Override
    public String getDataFilePath() {
        return this.file;
    }

    @Override
    public Account createAccount(Account account) throws AccountPersistException {
        Document document = readDocument();

        try{removeElements(account.getId(), document);} catch (Exception e){}

        Element element = document.getRootElement().element(ELEMENT_ACCOUNTS).addElement(ELEMENT_ACCOUNT);
        element.addElement(ELEMENT_ACCOUNT_ID).addText(account.getId());
        element.addElement(ELEMENT_ACCOUNT_NAME).addText(account.getName());
        element.addElement(ELEMENT_ACCOUNT_PASSWORD).addText(account.getPassword());
        element.addElement(ELEMENT_ACCOUNT_EMAIL).addText(account.getEmail());
        element.addElement(ELEMENT_ACCOUNT_ACTIVATED).addText(Boolean.toString(account.isActivated()));
        writeDocument(document);

        return account;
    }

    @Override
    public void deleteAccount(String id) throws AccountPersistException {
        Document document = readDocument();
        removeElements(id, document);

        writeDocument(document);
    }

    @Override
    public Account updateAccount(Account account) throws AccountPersistException {
        removeElements(account.getId(), readDocument());
        createAccount(account);
        return account;
    }

    @Override
    public Account readAccount(String id) throws AccountPersistException {
        Document document = readDocument();
        List<Element> accounts = findAccountElement(id, document);
        if(accounts.size() == 0) {
            throw new AccountPersistException("找不到账户" + id);
        } else if(accounts.size() > 1) {
            throw new AccountPersistException("账户数量大于1个");
        }

        return buildAccount(accounts.get(0));
    }
}
